View Javadoc
1   package org.apache.maven.surefire.junitcore;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.concurrent.ExecutionException;
26  import java.util.concurrent.ExecutorService;
27  import java.util.concurrent.Executors;
28  
29  import org.junit.runner.Computer;
30  import org.junit.runner.Runner;
31  import org.junit.runners.ParentRunner;
32  import org.junit.runners.Suite;
33  import org.junit.runners.model.InitializationError;
34  import org.junit.runners.model.RunnerBuilder;
35  import org.junit.runners.model.RunnerScheduler;
36  
37  /**
38   * Since SUREFIRE 2.18 this class is deprecated.
39   * Please use {@link org.apache.maven.surefire.junitcore.pc.ParallelComputerBuilder} instead.
40   *
41   * @author Kristian Rosenvold
42   */
43  @Deprecated
44  public class ConfigurableParallelComputer
45      extends Computer
46  {
47      private final boolean fClasses;
48  
49      private final boolean fMethods;
50  
51      private final boolean fixedPool;
52  
53      private final ExecutorService fService;
54  
55      private final List<AsynchronousRunner> nonBlockers =
56          Collections.synchronizedList( new ArrayList<AsynchronousRunner>() );
57  
58  
59      public ConfigurableParallelComputer()
60      {
61          this( true, true, Executors.newCachedThreadPool(), false );
62      }
63  
64      public ConfigurableParallelComputer( boolean fClasses, boolean fMethods )
65      {
66          this( fClasses, fMethods, Executors.newCachedThreadPool(), false );
67      }
68  
69      public ConfigurableParallelComputer( boolean fClasses, boolean fMethods, Integer numberOfThreads, boolean perCore )
70      {
71          this( fClasses, fMethods, Executors.newFixedThreadPool(
72              numberOfThreads * ( perCore ? Runtime.getRuntime().availableProcessors() : 1 ) ), true );
73      }
74  
75      private ConfigurableParallelComputer( boolean fClasses, boolean fMethods, ExecutorService executorService,
76                                            boolean fixedPool )
77      {
78          this.fClasses = fClasses;
79          this.fMethods = fMethods;
80          fService = executorService;
81          this.fixedPool = fixedPool;
82      }
83  
84      @SuppressWarnings( { "UnusedDeclaration" } )
85      public void close()
86          throws ExecutionException
87      {
88          for ( AsynchronousRunner nonBlocker : nonBlockers )
89          {
90              nonBlocker.waitForCompletion();
91          }
92  
93          fService.shutdown();
94          try
95          {
96              if ( !fService.awaitTermination( 10, java.util.concurrent.TimeUnit.SECONDS ) )
97              {
98                  throw new RuntimeException( "Executor did not shut down within timeout" );
99              }
100         }
101         catch ( InterruptedException e )
102         {
103             throw new RuntimeException( e );
104         }
105     }
106 
107     private Runner parallelize( Runner runner, RunnerScheduler runnerInterceptor )
108     {
109         if ( runner instanceof ParentRunner<?> )
110         {
111             ( (ParentRunner<?>) runner ).setScheduler( runnerInterceptor );
112         }
113         return runner;
114     }
115 
116     private RunnerScheduler getMethodInterceptor()
117     {
118         if ( fClasses && fMethods )
119         {
120             final AsynchronousRunner blockingAsynchronousRunner = new AsynchronousRunner( fService );
121             nonBlockers.add( blockingAsynchronousRunner );
122             return blockingAsynchronousRunner;
123         }
124         return fMethods ? new AsynchronousRunner( fService ) : new SynchronousRunner();
125     }
126 
127     private RunnerScheduler getClassInterceptor()
128     {
129         if ( fClasses )
130         {
131             return fMethods ? new SynchronousRunner() : new AsynchronousRunner( fService );
132         }
133         return new SynchronousRunner();
134     }
135 
136     @Override
137     public Runner getSuite( RunnerBuilder builder, java.lang.Class<?>[] classes )
138         throws InitializationError
139     {
140         Runner suite = super.getSuite( builder, classes );
141         return fClasses ? parallelize( suite, getClassInterceptor() ) : suite;
142     }
143 
144     @Override
145     protected Runner getRunner( RunnerBuilder builder, Class<?> testClass )
146         throws Throwable
147     {
148         Runner runner = super.getRunner( builder, testClass );
149         return fMethods && !isTestSuite( testClass ) ? parallelize( runner, getMethodInterceptor() ) : runner;
150     }
151 
152     private boolean isTestSuite( Class<?> testClass )
153     {
154         // Todo: Find out how/if this is enough
155         final Suite.SuiteClasses annotation = testClass.getAnnotation( Suite.SuiteClasses.class );
156         return ( annotation != null );
157     }
158 
159     @Override
160     public String toString()
161     {
162         return "ConfigurableParallelComputer{" + "classes=" + fClasses + ", methods=" + fMethods + ", fixedPool="
163             + fixedPool + '}';
164     }
165 
166 }